package generator.handle;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import generator.config.ComponentConfig;
import generator.config.MysqlTypeConvert;
import generator.config.TableMapConfig;
import generator.config.rules.IJavaType;
import generator.config.rules.ITypeConvert;
import generator.dao.IColumnDao;
import generator.dao.ITableDao;
import generator.dao.impl.ColumnDaoImpl;
import generator.dao.impl.TableDaoImpl;
import generator.model.Bean;
import generator.model.Column;
import generator.model.Property;
import generator.model.Table;
import generator.util.TableMapUtils;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * </p>
 *
 * @author angel.bin@aliyun.com
 * @since 2020-10-05 13:55
 */
public class ModelHandle {
    private final ITableDao I_TABLE_DAO = new TableDaoImpl();
    private final IColumnDao I_COLUMN_DAO = new ColumnDaoImpl();

    private final ITypeConvert I_TYPE_CONVERT = new MysqlTypeConvert();

    public List<Bean> listBeans(TableMapConfig tableMapConfig, ComponentConfig componentConfig) throws SQLException {
        List<Table> tables = I_TABLE_DAO.selectTables();
        List<Bean> beanList = new ArrayList<>();
        for (Table table : tables) {
            Bean bean = processTable(table, componentConfig, tableMapConfig);
            if (bean != null) {
                processColumns(bean, table, tableMapConfig);
                beanList.add(bean);
            }
        }
        return beanList;
    }

    private void processColumns(Bean bean, Table table, TableMapConfig tableMapConfig) throws SQLException {
        String name = table.getName();
        List<Column> columns = I_COLUMN_DAO.selectColumns(name);
        for (Column column : columns) {
            processColumn(bean, column, table, tableMapConfig);
        }
    }

    private void processColumn(Bean bean, Column column, Table table, TableMapConfig tableMapConfig) {
        List<Property> properties = bean.getProperties();
        if (properties == null) {
            properties = new ArrayList<>();
        }
        Set<String> packages = bean.getPackages();
        if (packages == null) {
            packages = new HashSet<>();
        }


        Property property = new Property();

        //列名
        String name = column.getName();
        property.setColumnName(name);

        //默认值
        property.setDefaultValue(column.getDefaultValue());


        //属性名称
        List<String> columnPrefixes = tableMapConfig.getColumnPrefixes();
        property.setName(TableMapUtils.getColumn(name, columnPrefixes));


        //json忽略字段
        List<String> jsonIgnores = tableMapConfig.getJsonIgnores();
        property.setIsIgnore(jsonIgnores != null && jsonIgnores.contains(name));

        //逻辑删除
        String tableLogic = tableMapConfig.getTableLogic();
        property.setIsLogicDel(StrUtil.equalsIgnoreCase(tableLogic, name));


        //主键和自增
        String key = column.getKey();
        property.setIsKey(StrUtil.isNotBlank(key) && StrUtil.equalsIgnoreCase(key, "PRI"));
        property.setIsAuto(StrUtil.isNotBlank(key) && table.getAutoIncrement() != null);

        //sql类型
        property.setSqlType(column.getDataType());

        //空值
        property.setIsNull(StrUtil.equalsIgnoreCase(column.getIsNull(), "YES"));


        //java类型
        IJavaType iJavaType = I_TYPE_CONVERT.processTypeConvert(column.getType());
        String pkg = iJavaType.getPkg();
        if (StrUtil.isNotBlank(pkg)) {
            packages.add(pkg);
        }
        property.setJavaType(iJavaType.getType());


        //注释
        String comment = column.getComment();
        if (StrUtil.isBlank(comment)) {
            System.err.println("表:[" + bean.getTableName() + "];字段:[" + name + "]无注释");
        }
        property.setComment(comment);


        properties.add(property);
        bean.setProperties(properties);
        bean.setPackages(packages);
    }

    private Bean processTable(Table table, ComponentConfig componentConfig, TableMapConfig tableMapConfig) {
        String name = table.getName();
        List<String> tableIgnores = tableMapConfig.getTableIgnores();
        // 忽略表
        if (CollUtil.isNotEmpty(tableIgnores)) {
            if (tableIgnores.contains(name)) {
                return null;
            }
        }
        //别名
        String alias = StrUtil.split(name, '_').parallelStream()
                .map(s -> s.substring(0, 1)).collect(Collectors.joining());

        //去除前缀,驼峰,大写首字母
        List<String> tablePrefixes = tableMapConfig.getTablePrefixes();
        String className = TableMapUtils.getClassName(name, tablePrefixes);

        Date createTime = table.getCreateTime();
        String dateTime = DateUtil.formatDateTime(createTime);
        String comment = table.getComment();
        if (StrUtil.isBlank(comment)) {
            System.err.println("表:[" + name + "]无注释");
        }
        return new Bean()
                .setTableName(name)
                .setAlias(alias)
                .setClassName(className)
                .setAuthor(componentConfig.getAuthor())
                .setData(dateTime)
                .setComment(comment);
    }


}
